package org.xhy.hrm.service.impl;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.xhy.hrm.asserts.GlobleAssert;
import org.xhy.hrm.constants.MQConstants;
import org.xhy.hrm.dto.SmsCodeDto;
import org.xhy.hrm.dto.SmsRedisDto;
import org.xhy.hrm.dto.SmsSendDto;
import org.xhy.hrm.globle.GlobleException;
import org.xhy.hrm.properties.ImgProperties;
import org.xhy.hrm.service.IVerifyCodeService;
import org.xhy.hrm.util.StrUtils;
import org.xhy.hrm.util.VerifyCodeUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
@Transactional
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private ImgProperties properties;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    //图形验证
    @Override
    public String imageCode(String key) {
        //随机数
        String imgCode = StrUtils.getComplexRandomString(properties.getCodelength());
        //将随机数存入redis中
        redisTemplate.opsForValue().set(key,imgCode,properties.getTimeout(), TimeUnit.MINUTES);
        //使用工具类返回，生成base64编码字符串返回
        return VerifyCodeUtils.VerifyCode(properties.getWidth(),properties.getLength(),imgCode);
    }

    //短信验证
    @Override
    public void sendSmsCode(SmsCodeDto dto) {
        String mobile = dto.getMobile();
        String imageCode = dto.getImageCode();
        String imageCodeKey = dto.getImageCodeKey();

        //校验参数
        GlobleAssert.hasText(mobile,"手机号不能为空");
        GlobleAssert.hasText(imageCode,"图形验证码不能为空");
        GlobleAssert.hasText(imageCodeKey,"图形验证key无效");

        //校验redis中的图形key是否正确
        String imgInRedisCodeKey = (String) redisTemplate.opsForValue().get(imageCodeKey);
        GlobleAssert.hasText(imgInRedisCodeKey,"验证码无效，请重试");
        GlobleAssert.isEquals(imgInRedisCodeKey,imageCode,"验证码不正确，请重新输入");

        //判断是否已经发送过验证
        //当前时间
        Date now = new Date();
        //key
        String key = properties.getSmsKey()+mobile;
        //通过key取redise值
        SmsRedisDto lastSmsRedisDto = (SmsRedisDto) redisTemplate.opsForValue().get(key);

        String smsCode = null;
        //取到值
        if (lastSmsRedisDto!=null){
            //在判断时间是否在一分钟以内
            if (now.getTime() - lastSmsRedisDto.getDateTime() < 60*1000){
                throw new GlobleException("操作过于频繁！");
            }
            //超过一分钟,取出redis中是验证码重新发送
            smsCode = lastSmsRedisDto.getSmsCode();
        } else {
            //如果没有则创建验证码发送
            smsCode = StrUtils.getRandomString(properties.getCodelength());
        }

        //发送
        String content = "尊敬的用户你好，您的验证码为"+ smsCode +","+ properties.getTimeout() +"分钟有效。";
        SmsSendDto smsSendDto = new SmsSendDto(content, Arrays.asList(mobile),null);
        rabbitTemplate.convertAndSend(MQConstants.NAME_EXCHANGE_HRM_TOPIC,"register.sms",smsSendDto);

        //保存验证码到redis
        redisTemplate.opsForValue().set(
                key,
                new SmsRedisDto(smsCode,now.getTime()),
                properties.getTimeout(),
                TimeUnit.MINUTES
                );

    }

}
